package maitaole.controller;

import maitaole.annotion.Autowire;
import maitaole.annotion.Parame;
import maitaole.annotion.RequestMapping;
import maitaole.utils.DateUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.URL;
import java.util.ArrayList;

/**
 * @Author 李杰
 * @Description 类的功能描述
 * @Date 2023/4/26
 */
public class BaseServlet<T> extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        //从url中获取methodName
        //String methodName = req.getParameter("method");
//        String methodName = req.getPathInfo().replace("/","");
//        System.out.println(methodName);
        String methodName = req.getPathInfo();
        //从类中获取方法
        Method[] methods = this.getClass().getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping configeValueMethod = method.getAnnotation(RequestMapping.class);
                //获取注解中的方法名称
                String string = configeValueMethod.value();
                if (methodName.equals(string)) {
                    //准备执行method的参数个数，类型，值（先有名称）

                    //先获取参数的名称(通过注解的方式)
                    Parameter[] parameters = method.getParameters();
                    ArrayList<Object> listValues = new ArrayList<>();
                    for (Parameter parameter : parameters) {
                        //先判断参数是否有注解
                        if (parameter.isAnnotationPresent(Parame.class)) {
                            //有注解通过注解来获取形参的名称
                            Parame annotation = parameter.getAnnotation(Parame.class);
                            String parameName = annotation.value();
                            //通过req来获取url中的值（Stirng）
                            String parameValue = req.getParameter(parameName);

                            //进行值类型的转换
                            Integer value = null;//参数的值
                            String parameClass = parameter.getType().getName();
                            if ("java.lang.Integer".equals(parameClass)) {
                                value = Integer.valueOf(parameValue);
                            }
                            listValues.add(value);

                        } else {

                            try {
                                Class c = parameter.getType();
                                Object o = c.newInstance();
                                T t = entryCase(req, (T) o);
                                listValues.add(t);


                            } catch (InstantiationException e) {
                                e.printStackTrace();
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }

                        }

                    }

                    try {
                        Object invoke = method.invoke(this, listValues.toArray());
                        resp.getWriter().print(invoke);

                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    public T entryCase(HttpServletRequest req, T develop)  {
        //完成对develop的赋值
        //获取类：
        Class<?> developClass = develop.getClass();
        //获取develop中所有的字段名，和类型
        //根据字段名来获取所有的set方法
        Field[] developFields = developClass.getDeclaredFields();
        Method[] methods = developClass.getDeclaredMethods();

        for (Field developField : developFields) {
            //获取各个字段的值
            String parameterValue = req.getParameter(developField.getName());
            //获取各个字段的类型
            Object value = null;
            if (parameterValue != null) {
                if ("java.lang.Integer".equals(developField.getType().getName())) {
                    value = Integer.valueOf(parameterValue);
                }
                if ("java.lang.String".equals(developField.getType().getName())) {
                    value = String.valueOf(parameterValue);
                }
                if ("java.util.Date".equals(developField.getType().getName())) {
                    value = DateUtils.strToDate(parameterValue);
                }

                String st = "set" + developField.getName().substring(0, 1).toUpperCase() + developField.getName().substring(1);
                for (Method method : methods) {
                    if (st.equals(method.getName())) {
                        //执行set方法
                        try {
                            method.invoke(develop, value);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                }


            }
        }

        return  develop;
    }

    public void  autoController(ServletContext sc){
        String serverPackage = "com.qfedu.controller";
        String serverPath = serverPackage.replace(".", "/");

        URL url = maitaole.controller.BaseServlet.class.getClassLoader().getResource(serverPath);
        String packagePath = url.getPath();

        File file = new File(packagePath);
        File[] files = file.listFiles();
        for (File file1 : files) {
            String fileName = file1.getName();
            if (fileName.endsWith(".class")){
                try {
                    String replace = fileName.replace(".class", "");
                    Class<?> aClass = Class.forName(serverPackage + "." + replace);
                    //创建service的类
                    Object o = aClass.newInstance();
                    System.out.println(o);


                    //完成对controller层中service方法的封装
                    //访问类里面的字段
                    Field[] fields = aClass.getDeclaredFields();
                    System.out.println(fields);

                    for (Field field : fields) {
                        //访问是否有注解
                        if (field.isAnnotationPresent(Autowire.class)){
                            try {

                                //有注解的要注入值
                                String name = field.getName();
                                String setMethodName="set"+name.substring(0,1).toUpperCase()+name.substring(1);
                                Method setMethod = aClass.getDeclaredMethod(setMethodName, field.getType());

                                //获取执行方法的参数
                                Object attribute = sc.getAttribute(field.getType().getName());
                               //contrller层的
                                setMethod.invoke(this,attribute);

                            } catch (NoSuchMethodException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

